/*
Author: Sheila Tabuena
Filename: utilities.js
Date Created: APR-09-2009

Contains general utility functions, including:
    addNode(parent, element, nameId, text) -- creates new node of type "element",
           appends it to "parent", sets name and id attributes of new node to "nameId",
           optionally creates text node with "text" and appends it, returns the new node. 
    findNode(tree,tagName,attribute, value)  -- Looks through an xml "tree" to find a node  
           with a "tagname" and a particular "attribute" / "value" pair. Returns the node 
           if foundand returns null if no such node is found. 
    toConsole(data)--Writes contents of "data" to an element with the id of 'console'
           by creating a div node, creating a text node containing "data", append
           text to div, div to console node. Used for development & debugging 
    insertNode(sibling, element, nameId, text) -- Creates a new node of the type "element", 
           inserts it right before the node "sibling".
           Sets the name and id attributes of the new node to "nameId".
           If "text" is present, this also creates a text node with "text"
           in it and appends it to the new node. Returns the new node.
    makeNode(element, nameId, text) -- Creates a new node of the type "element", 
           but does not append it. Useful when node placement must be deferred.
           Sets the name and id attributes of the new node to "nameId".
           If "text" is present, this also creates a text node with "text"
           in it and appends it to the new node. Returns the new node.
    dropDown(items, enclosingTagId, callBack)-- a function that makes and 
            updates a drop down menu containing "items" as the options,the 
            menu is enclosed by "enclosingTagId" and has "callback" as its 
            onchange event. returns selectNode for the convenience of calling program 
    updateItems(selectNode,items)--after the drop down menu is there, this changes the options 
           on "selectNode" to be "items"
    findObject (array, attribute, value)--looks through an "array" of objects to find the 
             object with a particular "attribute/value" pair. Returns the object.
    parseXML(response,tag)--This function parses out "response" and puts values inside 
            "tag" into an array "list" which it returns
    getTagArray(response,tagName)--This function reads XML "response" and puts the text 
             inside "tag" into an array "list" which it returns
    getRandom(pickArray)--returns a random entry from list "pickArray"
*/


/* Creates a new node of the type "element", appends it to "parent".
   Sets the name and id attributes of the new node to "nameId".
   If "text" is present, this also creates a text node with "text"
   in it and appends it to the new node. Returns the new node.
*/
function addNode(parent, element, nameId, text)
{
   var newNode = document.createElement(element);
   newNode.setAttribute("id",nameId);
   newNode.setAttribute("name",nameId);
   parent.appendChild(newNode);
   if (text != "")
   {
      var textNode = document.createTextNode(text);
      newNode.appendChild(textNode);
   }
   return newNode;
}

/* Writes contents of "data" to an element with the id of 'console'
   by creating a div node, creating a text node containing "data", append
   text to div, div to console node. Used for development & debugging */
function toConsole(data)
{ var console = document.getElementById('console');
  if (console!=null)
  { var newline = document.createElement("div");
    console.appendChild(newline);
    var txt = document.createTextNode(data);
    newline.appendChild(txt);
  }
}

/* Looks through an xml "tree" to find a node with a "tagname" and 
   a particular "attribute" / "value" pair. Returns the node if found
   and returns null if no such node is found. */
function findNode(tree,tagName,attribute, value)
{
   var targetNode = null;
   var nodeArray = tree.getElementsByTagName(tagName);
   // find the first node in the nodeArray with attribute==value
   for (i=0; i<nodeArray.length && targetNode==null; ++i)
   {
       if (nodeArray[i].getAttribute(attribute) == value )
       {
           targetNode = nodeArray[i];
      }
  }
  return targetNode;
}

/* Creates a new node of the type "element", inserts it 
   right before the node "sibling".
   Sets the name and id attributes of the new node to "nameId".
   If "text" is present, this also creates a text node with "text"
   in it and appends it to the new node. Returns the new node.
*/
function insertNode(sibling, element, nameId, text)
{
   var newNode = makeNode(element, nameId, text);
   sibling.parentNode.insertBefore(newNode,sibling);
   return newNode;
}

/* Creates a new node of the type "element", but does not append it.
   Useful when node placement must be deferred.
   Sets the name and id attributes of the new node to "nameId".
   If "text" is present, this also creates a text node with "text"
   in it and appends it to the new node. Returns the new node.
*/
function makeNode(element, nameId, text)
{
   var newNode = document.createElement(element);
   newNode.setAttribute("id",nameId);
   newNode.setAttribute("name",nameId);
   if (text != "")
   {
      var textNode = document.createTextNode(text);
      newNode.appendChild(textNode);
   }
   return newNode;
}

// a function that makes and updates a drop down menu containing "items" as the options,
// the menu is enclosed by "enclosingTagId" and has "callback" as its onchange event.
// returns selectNode for the convenience of calling program
function dropDown(items, enclosingTagId, callBack)
{
  var selectNode = document.getElementById(enclosingTagId);
  selectNode.setAttribute("onchange", callBack);
  updateItems(selectNode,items);
  return selectNode;
}

// after the drop down menu is there, this changes the options on "selectNode" to be items
function updateItems(selectNode,items)
{
  selectNode.options.length = 0; // get rid of old options in the select node
  for ( i = 0; i < items.length; ++i)
  {
    addNode (selectNode, "option", items[i], items[i]);
  }
}

// looks through an array of objects to find the object with
// a particular attribute/value pair. Returns the object.
function findObject (array, attribute, value)
{ var targetObject = null;
  // find the object in array with attribute == value
  for (i = 0; i < array.length && targetObject==null; ++i)
  { if (eval("array[i]."+attribute) == value)
    { 
      targetObject = array[i];
    }
  }
  return targetObject;
}

/* This function parses out "response" and puts text values inside "tag" into an array 
   "list" which it returns */
function parseXML(response,tag)
{
  var list = new Array();
  var index = 0;
  sTag = "<" + tag + ">";
  eTag = "</" + tag + ">";
  var start = response.indexOf(sTag);
  var end = response.indexOf(eTag,start);
  while (response.length > 0 && start >= 0)
  {
    list[index++] = response.slice(start + sTag.length,end);
    response = response.slice(start + sTag.length); 
    start = response.indexOf(sTag);
    end = response.indexOf(eTag,start);
  }
  return list;
}
/* This function reads XML "response" and puts the text inside "tag" into an array 
   "list" which it returns */
function getTagArray(response,tagName)
{
  var list = [];
  var nodeArray = response.getElementsByTagName(tagName);
  for (i=0;i<nodeArray.length;++i)
  {
    list[i] = nodeArray[i].firstChild.data
  }
  return list;
}

// returns a random entry from list "pickArray"
function getRandom(pickArray)
{
  var randomIndex=Math.floor(Math.random()* pickArray.length)
  return pickArray[randomIndex];
}
